package com.hu.utils;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.hu.pojo.CommonStatisticsReq;
import com.hu.pojo.PublicPeriod;
import com.hu.pojo.Result;
import com.hu.pojo.TimeRequestEnum;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
 * @功能：
 * @版本： V1
 * @版权： 信息技术有限公司（http://www.mychery.com/）
 * @作者： 磐石战队开发组  00355760
 * @日期： 2024/10/28 9:08
 */
public class ResultUtil {
    private static final String DATE_PATTERN = "yyyy-MM-dd HH:mm:ss";

    // 计算时间列表
    public Result getTimeList(CommonStatisticsReq commonStatisticsReq) {
        int year = Integer.parseInt(commonStatisticsReq.getYear());
        int periodValue = Integer.parseInt(commonStatisticsReq.getPeriodValue());

        switch (commonStatisticsReq.getPeriodType()) {
            case "year":
                return TimeToChineseUtil.generateYearPeriods(year);
            case "quarter":
                return TimeToChineseUtil.generateQuarterPeriods(year, periodValue);
            case "month":
                return TimeToChineseUtil.generateMonthPeriods(year, periodValue);
            default:
                return TimeToChineseUtil.generateWeekPeriods(year, periodValue);
        }
    }

    // 根据当前周期数据，将Result对象转换为可计算同比增长率的Result对象
    public Result currentConvert(Result result, CommonStatisticsReq req) {

        List<String> titles = new ArrayList<>(result.getTitles());
        List<PublicPeriod> periods = new ArrayList<>(result.getPeriods());

        LocalDateTime currentDate = LocalDateTime.parse(periods.get(periods.size() - 1).getEnd(), DateTimeFormatter.ofPattern(DATE_PATTERN));
        int nDays = getDays(periods.get(periods.size() - 1));

        Date endofDate = Date.from(currentDate.toLocalDate().atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());
        List<PublicPeriod> newPeriods = new ArrayList<>();

        for (int i = 0; i < periods.size(); i++) {
            PublicPeriod period = periods.get(i);
            LocalDateTime start = LocalDateTime.parse(period.getStart(), DateTimeFormatter.ofPattern(DATE_PATTERN));
            LocalDateTime originalEnd = LocalDateTime.parse(period.getEnd(), DateTimeFormatter.ofPattern(DATE_PATTERN));
            LocalDateTime end = start;

            if (TimeRequestEnum.YEAR.getDescription().equals(req.getPeriodType())) {
                if (ObjectUtil.equal(currentDate.toLocalDate(), DateUtil.endOfMonth(endofDate).toLocalDateTime().toLocalDate())) {
                    if (i == periods.size() - 1) {
                        end = currentDate;
                    } else {
                        end = DateUtil.endOfMonth(Date.from(start.toLocalDate().plusMonths(endofDate.getMonth()).atStartOfDay().atZone(ZoneId.systemDefault()).toInstant())).toLocalDateTime();
                    }
                }
                else {
                    if (i == periods.size() - 1) {
                        end = currentDate;
                    } else {
                        end = DateUtil.beginOfMonth
                                        (Date.from(start.toLocalDate().plusMonths(endofDate.getMonth()).atStartOfDay().atZone(ZoneId.systemDefault()).toInstant()))
                                .toLocalDateTime().plusDays(currentDate.getDayOfMonth()-1).withHour(23).withMinute(59).withSecond(59);
                    }
                }
            } else if (TimeRequestEnum.QUARTER.getDescription().equals(req.getPeriodType())) {
                int monthValue = currentDate.toLocalDate().getMonthValue();
                if (ObjectUtil.equal(monthValue%3,0) && currentDate.toLocalDate().equals(currentDate.toLocalDate().withDayOfMonth(currentDate.toLocalDate().lengthOfMonth()))){
                    end = originalEnd;
                } else {
                    end = end.plusDays(nDays).withHour(23).withMinute(59).withSecond(59);
                }
            } else if (TimeRequestEnum.MONTH.getDescription().equals(req.getPeriodType())) {
                if (currentDate.getMonthValue() != 2) {
                    if (ObjectUtil.equal(currentDate.toLocalDate(), DateUtil.endOfMonth(endofDate).toLocalDateTime().toLocalDate())) {
                        end = DateUtil.endOfMonth(Date.from(end.toLocalDate().atStartOfDay().atZone(ZoneId.systemDefault()).toInstant())).toLocalDateTime();
                    } else {
                        if (ObjectUtil.equal(nDays, DateUtil.endOfMonth(Date.from(end.toLocalDate().atStartOfDay().atZone(ZoneId.systemDefault()).toInstant())).dayOfMonth())) {
                            end = DateUtil.endOfMonth(Date.from(end.toLocalDate().atStartOfDay().atZone(ZoneId.systemDefault()).toInstant())).toLocalDateTime();
                        } else {
                            end = end.plusDays(Math.min(nDays, DateUtil.endOfMonth(endofDate).dayOfMonth()));
                        }
                    }
                } else {
                    if (ObjectUtil.equal(currentDate.toLocalDate(), DateUtil.endOfMonth(endofDate).toLocalDateTime().toLocalDate())) {
                        end = DateUtil.endOfMonth(Date.from(end.toLocalDate().atStartOfDay().atZone(ZoneId.systemDefault()).toInstant())).toLocalDateTime();
                    } else {
                        end = end.plusDays(nDays);
                    }
                }
            } else if (TimeRequestEnum.WEEK.getDescription().equals(req.getPeriodType())) {
                int dayOfWeekDifference = end.plusDays(nDays).getDayOfWeek().getValue() - start.getDayOfWeek().getValue();
                if (dayOfWeekDifference < 0) {
                    dayOfWeekDifference += 7;
                }
                end = end.plusDays(dayOfWeekDifference);
            }
            newPeriods.add(new PublicPeriod(start.format(DateTimeFormatter.ofPattern(DATE_PATTERN)), end.format(DateTimeFormatter.ofPattern(DATE_PATTERN))));
        }
        return new Result(titles, newPeriods);
    }

    private static int getDays(PublicPeriod lastPeriod) {
        LocalDate lastPeriodStart = LocalDate.parse(lastPeriod.getStart(), DateTimeFormatter.ofPattern(DATE_PATTERN));
        LocalDate lastPeriodEnd = LocalDate.parse(lastPeriod.getEnd(), DateTimeFormatter.ofPattern(DATE_PATTERN));
        return (int) lastPeriodEnd.toEpochDay() - (int) lastPeriodStart.toEpochDay();
    }

    // 移除第一个元素
    private Result removeByOne(Result result) {
        List<String> titles = new ArrayList<>(result.getTitles());
        List<PublicPeriod> periods = new ArrayList<>(result.getPeriods());
        titles.remove(0);
        periods.remove(0);
        return new Result(titles, periods);
    }

    // 计算增长率列表
    private List<Double> calculateGrowthRates(List<Integer> checkInBar) {
        List<Double> growthRates = new ArrayList<>();
        for (int i = 1; i < checkInBar.size(); i++) {
            int previousValue = checkInBar.get(i - 1);
            int currentValue = checkInBar.get(i);
            if (ObjectUtil.equal(previousValue, 0) && ObjectUtil.equal(currentValue, 0)) {
                growthRates.add(0.0);
            } else if(ObjectUtil.equal(previousValue, 0)){
                growthRates.add(Double.MAX_VALUE);
            } else {
                double growthRate = (currentValue - previousValue) / (double) previousValue * 100L;
                growthRates.add(growthRate);
            }
        }
        return growthRates;
    }
}
